#include "material.h"

#include "vector3.h"
#include <cmath>
#include <cstdio>
#include <cstdlib>

namespace raytrace {

// static
Vector3 Material::GetPointOnHemisphere(Vector3Arg normal, float& pdf) {
	// Basis construction.
	Vector3 axis;
	{
		const float fX = fabsf(normal.x_);
		const float fY = fabsf(normal.y_);
		const float fZ = fabsf(normal.z_);
		
		if(fX < fY) {
			if(fY < fZ)
				axis = Vector3(0, 1, 0);
			else 
				axis = Vector3(0, 0, 1);
		} else if(fX < fZ)
			axis = Vector3(1, 0, 0);
		else
			axis = Vector3(0, 0, 1);
	}
	
	Vector3 u = Vector3::cross(axis, normal); 
	u.normalize();
	
	Vector3 v = Vector3::cross(normal, u);
	v.normalize();
	
	// Cosine weighted importance sample
	const float r1 = drand48();
	const float r2 = drand48();
	
	const float phi = 2 * M_PI * r1;
	// theta is acosf(sqrt(r2));
	
	const float x = cosf(phi) * sqrtf(1 - r2);
	const float y = sinf(phi) * sqrtf(1 - r2);
	const float z = sqrtf(r2);
	
	Vector3 d = Vector3::scale(u, x);
  d = Vector3::add(d, Vector3::scale(v, y));
  d = Vector3::add(d, Vector3::scale(normal, z));
	d.normalize();
	
	pdf = z / M_PI;
	
	return d;
}

Material::Material(Vector3Arg reflectance_color, 
                   Vector3Arg emittance_color)
    : reflectance_color_(reflectance_color),
      emittance_color_(emittance_color) {
}

void Material::DumpToLog() const {
  printf("|   +- t: %s\n", type());
  printf("|   +- r: %.3f %.3f %.3f\n",
         reflectance_color_.x_, reflectance_color_.y_, reflectance_color_.z_);
  printf("|   +- e: %.3f %.3f %.3f\n",
         emittance_color_.x_, emittance_color_.y_, emittance_color_.z_);
}

}
